package com.atguigu.gmall.item.service;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.item.feign.GmallPmsClient;
import com.atguigu.gmall.item.feign.GmallSmsClient;
import com.atguigu.gmall.item.feign.GmallWmsClient;
import com.atguigu.gmall.item.vo.ItemVo;
import com.atguigu.gmall.pms.entity.*;
import com.atguigu.gmall.pms.vo.ItemGroupVo;
import com.atguigu.gmall.pms.vo.SaleAttrValueVo;
import com.atguigu.gmall.sms.vo.ItemSaleVo;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;
@Service
@Slf4j
public class ItemService {
    @Autowired
    GmallPmsClient gmallPmsClient;
    @Autowired
    GmallSmsClient gmallSmsClient;
    @Autowired
    GmallWmsClient gmallWmsClient;
    @Autowired
    ThreadPoolExecutor threadPoolExecutor;

    public ItemVo loadData(Long skuId) {
        ItemVo itemVo = new ItemVo();
//        1. 根据skuId查询sku（已有）
        CompletableFuture<SkuEntity> skuFuture = CompletableFuture.supplyAsync(() -> {
            ResponseVo<SkuEntity> skuEntityResponseVo = gmallPmsClient.querySkuById(skuId);
            SkuEntity skuEntity = skuEntityResponseVo.getData();
            itemVo.setSkuId(skuId);
            itemVo.setTitle(skuEntity.getTitle());
            itemVo.setSubTitle(skuEntity.getSubtitle());
            itemVo.setPrice(skuEntity.getPrice());
            itemVo.setWeight(skuEntity.getWeight());
            itemVo.setDefaultImage(skuEntity.getDefaultImage());
            return skuEntity;
        }, threadPoolExecutor);
//        2. 根据sku中的三级分类id查询一二三级分类
        CompletableFuture<Void> catesFuture = skuFuture.thenAcceptAsync(skuEntity -> {
            ResponseVo<List<CategoryEntity>> catesResponseVo =
                    gmallPmsClient.queryLvlAllCategoriesByCid3(skuEntity.getCategoryId());
            itemVo.setCategories(catesResponseVo.getData());

        }, threadPoolExecutor);
//        3. 根据sku中的品牌id查询品牌（已有）
        CompletableFuture<Void> brandFuture = skuFuture.thenAcceptAsync(skuEntity -> {
            ResponseVo<BrandEntity> brandEntityResponseVo = gmallPmsClient.queryBrandById(skuEntity.getBrandId());
            BrandEntity brandEntity = brandEntityResponseVo.getData();
            if (brandEntity != null) {
                itemVo.setBrandId(brandEntity.getId());
                itemVo.setBrandName(brandEntity.getName());
            }
        }, threadPoolExecutor);
//        4. 根据sku中的spuId查询spu信息（已有）
        CompletableFuture<Void> spuFuture = skuFuture.thenAcceptAsync(skuEntity -> {
            ResponseVo<SpuEntity> spuEntityResponseVo = gmallPmsClient.querySpuById(skuEntity.getId());
            SpuEntity spuEntity = spuEntityResponseVo.getData();
            if (spuEntity != null) {
                itemVo.setSpuId(spuEntity.getId());
                itemVo.setSpuName(spuEntity.getName());
            }
        }, threadPoolExecutor);
//        5. 根据skuId查询sku图片列表
        CompletableFuture<Void> imagesFuture = CompletableFuture.runAsync(() -> {
            ResponseVo<List<SkuImagesEntity>> imagesResponseVo = gmallPmsClient.queryImagesBySkuId(skuId);
            List<SkuImagesEntity> skuImagesEntities = imagesResponseVo.getData();
            itemVo.setImages(skuImagesEntities);
        }, threadPoolExecutor);
//        6. 根据skuId查询营销信息（sms）
        CompletableFuture<Void> salesFuture = CompletableFuture.runAsync(() -> {
            ResponseVo<List<ItemSaleVo>> salesResponseVo = gmallSmsClient.querySalesBySkuId(skuId);
            List<ItemSaleVo> itemSaleVos = salesResponseVo.getData();
            itemVo.setSales(itemSaleVos);
        }, threadPoolExecutor);
//        7. 根据skuId查询sku的库存信息（已有）
        CompletableFuture<Void> storeFuture = CompletableFuture.runAsync(() -> {
            ResponseVo<List<WareSkuEntity>> wareResponseVo = gmallWmsClient.queryWareSkusBySkuId(skuId);
            List<WareSkuEntity> wareSkuEntities = wareResponseVo.getData();
            itemVo.setStore(wareSkuEntities.stream().anyMatch(wareSkuEntity -> wareSkuEntity.getStock() - wareSkuEntity.getStockLocked() > 0));
        }, threadPoolExecutor);
//        8. 根据sku中的spuId查询spu下的所有销售属性
        CompletableFuture<Void> saleAttrsFuture = skuFuture.thenAcceptAsync(skuEntity -> {
            ResponseVo<List<SaleAttrValueVo>> saleAttrsResponseVo =
                    gmallPmsClient.querySaleAttrsBySpuId(skuEntity.getSpuId());
            List<SaleAttrValueVo> saleAttrValueVos = saleAttrsResponseVo.getData();
            itemVo.setSaleAttrs(saleAttrValueVos);
        }, threadPoolExecutor);
//        9. 根据skuId查询当前sku的销售属性(高亮)
        CompletableFuture<Void> saleAttrFuture = CompletableFuture.runAsync(() -> {
            ResponseVo<List<SkuAttrValueEntity>> saleAttrResponseVo = gmallPmsClient.querySaleAttrValueBySkuId(skuId);
            List<SkuAttrValueEntity> skuAttrValueEntities = saleAttrResponseVo.getData();
            if (skuAttrValueEntities != null) {
                itemVo.setSaleAttr(skuAttrValueEntities.stream().collect(Collectors.toMap(SkuAttrValueEntity::getAttrId, SkuAttrValueEntity::getAttrValue)));
            }
        }, threadPoolExecutor);

//        10. 根据sku中的spuId查询spu下所有sku：销售属性组合与skuId映射关系
//        {'白色,8G,128G': 4, '白色,8G,256G': 5, '白色,8G,512G': 6, '白色,12G,128G': 7}
        CompletableFuture<Void> mappingFuture = skuFuture.thenAcceptAsync(skuEntity -> {
            ResponseVo<Map<String, Object>> mapResponseVo =
                    gmallPmsClient.querySaleAttrsMappingSkuIdBySpuId(skuEntity.getSpuId());
            Map<String, Object> map = mapResponseVo.getData();
            itemVo.setSkuJsons(map);
        }, threadPoolExecutor);
//        11. 根据sku中spuId查询spu的描述信息（已有）
        CompletableFuture<Void> descFuture = skuFuture.thenAcceptAsync(skuEntity -> {
            ResponseVo<SpuDescEntity> spuDescEntityResponseVo = gmallPmsClient.querySpuDescById(skuEntity.getSpuId());
            SpuDescEntity descEntity = spuDescEntityResponseVo.getData();
            if (StringUtils.isNotBlank(descEntity.getDecript()) && descEntity != null) {
                String[] split = StringUtils.split(descEntity.getDecript(), ",");
                itemVo.setSpuImages(Arrays.asList(split));
            }
        }, threadPoolExecutor);
//        12. 根据分类id、spuId及skuId查询分组及组下的规格参数值
        CompletableFuture<Void> groupFuture = skuFuture.thenAcceptAsync(skuEntity -> {
            ResponseVo<List<ItemGroupVo>> groupResponseVo =
                    gmallPmsClient.queryGroupWithAttrValuesByCidAndSpuIdAndSkuId(skuEntity.getCategoryId(),
                            skuEntity.getSpuId(), skuId);
            List<ItemGroupVo> itemGroupVos = groupResponseVo.getData();
            itemVo.setGroups(itemGroupVos);
        }, threadPoolExecutor);
        
        //组合方法并阻塞
        CompletableFuture.allOf(catesFuture,brandFuture,spuFuture,imagesFuture,
                salesFuture,storeFuture,saleAttrsFuture,saleAttrFuture,mappingFuture,
                descFuture,groupFuture).exceptionally(t->{
                log.error("异步任务出现了异常：{}",t.getMessage());
                return null;
        }).join();
        return itemVo;
    }

    @Autowired
    TemplateEngine templateEngine;
    //生成静态页面
    public void createHtml(ItemVo itemVo) {
        //多线程异步生成静态页面和当前用户无关，只是为下一个用户准备的，所以不用主线程
        //try catch有错误也不影响
        threadPoolExecutor.execute(()->{
            try(PrintWriter printWriter = new PrintWriter("D:\\html\\" + itemVo.getSkuId() + ".html")) {
                // 上下文对象
                Context context = new Context();
                context.setVariable("itemVo",itemVo);
                // 文件流
                templateEngine.process("item",context,printWriter);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        });

    }
}
